package online.longzipeng.cinemasys.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import online.longzipeng.cinemasys.common.exception.AppException;
import online.longzipeng.cinemasys.common.result.ResponseEnum;
import online.longzipeng.cinemasys.config.RedisConfig;
import online.longzipeng.cinemasys.dto.order.OderQueryResponse;
import online.longzipeng.cinemasys.dto.order.OrderDetailResponseDTO;
import online.longzipeng.cinemasys.entity.OrderDetail;
import online.longzipeng.cinemasys.entity.OrderHead;
import online.longzipeng.cinemasys.entity.Seat;
import online.longzipeng.cinemasys.mapper.OrderDetailMapper;
import online.longzipeng.cinemasys.mapper.OrderHeadMapper;
import online.longzipeng.cinemasys.mapper.SeatMapper;
import online.longzipeng.cinemasys.service.OrderHeadService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import online.longzipeng.cinemasys.vo.order.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author lzp
 * @since 2021-04-09
 */
@Service
public class OrderHeadServiceImpl extends ServiceImpl<OrderHeadMapper, OrderHead> implements OrderHeadService {

    @Autowired
    OrderDetailMapper orderDetailMapper;
    @Autowired
    OrderHeadMapper orderHeadMapper;
    @Autowired
    SeatMapper seatMapper;
    @Autowired
    RedisTemplate redisTemplate;

    private DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Override
    @Transactional
    public String add(OrderSaveVO orderSaveVO) {
        // 先保存订单头
        OrderHead orderHead = new OrderHead();
//        orderHead.setStatus(orderSaveVO.getStatus());
        // 雪花算法生成订单号
        orderHead.setNum(IdWorker.getId()+"");
        orderHead.setCustomerId(orderSaveVO.getCustomerId());
        BigDecimal allPrice = orderSaveVO.getAllPrice().divide(BigDecimal.TEN).divide(BigDecimal.TEN);
        orderHead.setAllPrice(allPrice);
        save(orderHead);
        // 从redis中获取座位集合
        Object o = redisTemplate.opsForValue().get(RedisConfig.SESSION_KEY + orderSaveVO.getSessionId());
        List<Seat> seats = JSONObject.parseArray(o.toString(), Seat.class);
        // 再查询出订单头的id
        QueryWrapper<OrderHead> qwOrderHead = new QueryWrapper<>();
        qwOrderHead.eq("num",orderHead.getNum());
        OrderHead qOrderHead = getOne(qwOrderHead);
        List<Long> seatIds = orderSaveVO.getSeatIds();
        OrderDetail orderDetail;
        // 遍历座位生成订单详情
        for (Long id : seatIds) {
            orderDetail = new OrderDetail();
            orderDetail.setSessionId(orderSaveVO.getSessionId());
            orderDetail.setSeatId(id);
            orderDetail.setOrderHeadId(qOrderHead.getId());
            try {
                setSeatStatus(seats,id);
            } catch (AppException e) {
                // 如果被占用就删除刚刚添加的订单头和订单详情，并返回错误
                removeById(qOrderHead.getId());
                QueryWrapper<OrderDetail> qwOrderDetail = new QueryWrapper<>();
                qwOrderDetail.eq("order_head_id",qOrderHead.getId());
                orderDetailMapper.delete(qwOrderDetail);
                throw e;
            }
            orderDetailMapper.insert(orderDetail);
            orderDetail = null;
        }
        // 将最新的场次座位更新到缓存中
        redisTemplate.opsForValue().set(RedisConfig.SESSION_KEY+orderSaveVO.getSessionId(),JSONObject.toJSONString(seats));
        return orderHead.getNum();
    }

    /**
     * 遍历座位集合设置座位状态
     */
    private void setSeatStatus(List<Seat> seats,Long id){
        for (Seat seat : seats) {
            if (seat.getId().equals(id)) {
                if (seat.getStatus() == 0) {
                    seat.setStatus(1);
                }else {
                    AppException appException = new AppException(ResponseEnum.EXCEPTION_SEAT_IS_TAKE_UP);
                    appException.setMessage(seat.getName()+"已被预订！！请重新选择！！");
                    throw appException;
                }
            }
        }
    }

    @Override
    public void updateOrderHead(OrderHead orderHead) {

    }

    @Override
    public IPage<OderQueryResponse> getListPage(OrderQueryVO queryVO) {
        Page<OderQueryResponse> page = new Page<>(queryVO.getPage(),queryVO.getSize());
        QueryWrapper<OderQueryResponse> qw = new QueryWrapper<>();
        // 判断排序
        if ("desc".equals(queryVO.getSort())) {
            qw.orderByDesc("id");
        }else {
            qw.orderByAsc("id");
        }
        return orderHeadMapper.getListPage(page,qw);
    }

    @Override
    @Transactional
    public void delete(Long id) {
        // 先删除订单详情再删除订单
        QueryWrapper<OrderDetail> qwOrderDetail = new QueryWrapper<>();
        qwOrderDetail.eq("order_head_id",id);
        orderDetailMapper.delete(qwOrderDetail);
        removeById(id);
    }

    @Override
    public List<OderQueryResponse> getListByCustomerAndStatus(Integer status, Long id) {
        QueryWrapper<OderQueryResponse> qw = new QueryWrapper<>();
        qw.eq("status",status);
        qw.eq("customer_id",id);
        qw.orderByDesc("id");
        List<OderQueryResponse> orderList = orderHeadMapper.getListByCustomerAndStatus(qw);
        for (OderQueryResponse order : orderList) {
            // 拼接电影 和时间 影厅
            StringBuilder sb = new StringBuilder(order.getOrderDetails().get(0).getSession().getMovie().getName());
            sb.append(" ");
            sb.append(dtf.format(order.getOrderDetails().get(0).getSession().getStartTime()));
            sb.append(" ");
            sb.append(order.getOrderDetails().get(0).getSession().getHall().getName());
            sb.append(" ");
            for (OrderDetailResponseDTO orderDetail : order.getOrderDetails()) {
                // 拼接座位
                sb.append(orderDetail.getSeat().getName());
                sb.append(" ");
            }
            order.setOrderText(sb.toString());
        }
        return orderList;
    }
}
